package com.twb.fileCenter.ftp;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.aspectj.util.FileUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/** 
 * @ClassName: FtpUtil 
 * @Description: ftp工具类
 * @author DSY
 * @date 2017年4月19日 下午5:34:37 
 */ 
@Component
public class FtpUtil {
	private static Logger logger = LoggerFactory.getLogger(FtpUtil.class);
	private static Map<String,FTPClient> ftpClients;
	private static String defaultKey="default";
	
	@Autowired
	private FtpConfigProperties ftpConfigProperties;
	
	private static FtpConfigProperties ftpConfigs;
	
	@PostConstruct
	public void init() {
		ftpConfigs = ftpConfigProperties;
	}

	public static FTPClient createConnection() {
		return createConnection(defaultKey);
	}
	/**
	 * @Title: createConnection
	 * @Class: FtpUtils.java
	 * @Package: com.dths.core
	 * @Description:获取属性文件中ftp连接信息并进行ftp连接
	 * @return
	 * @AuthorOriginally LQY
	 * @date 2017年4月10日 下午2:17:34
	 */
	private static FTPClient createConnection(String key) {
		FTPClient ftpClient = new FTPClient();
		if(ftpClients!=null){
			ftpClient = ftpClients.get(key);
		}

		FtpConfigProperties.FtpSingleProperties ftpConfig = ftpConfigs.getFtps().get(key);
		if(null != ftpClient && ftpClient.isConnected()){
			return ftpClient;
		}
		// 创建FTPClient对象
		ftpClient = new FTPClient();
		ftpClient.setControlEncoding("UTF-8");
		int reply = 0;
		// 连接FTP服务器
		// 如果采用默认端口，可以使用ftp.connect(ip)的方式直接连接FTP服务器
		try {
			ftpClient.connect(ftpConfig.getHost(), ftpConfig.getPort());
			// 登录ftp
			ftpClient.login(ftpConfig.getUsername(), ftpConfig.getPassword());
			ftpClient.enterLocalPassiveMode();
			// 设置文件类型
			ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
			// 看返回的值是不是reply>=200&&reply<300 如果是，表示登陆成功
			reply = ftpClient.getReplyCode();
			// 以2开头的返回值就会为真
			if (!FTPReply.isPositiveCompletion(reply)) {
				ftpClient.disconnect();
				return ftpClient;
			}
			logger.debug("ftpServer connect success");
		} catch (IOException e) {
			logger.error("ftpServer connect failed");
			e.printStackTrace();
		}
		return ftpClient;

	}
	public static Boolean uploadFile(String filepath, String filename, InputStream inputStream) {
		return uploadFile(defaultKey,filepath,filename,inputStream);
	}
		/**
         * @Title: uploadFile
         * @Class: FtpUtil.java
         * @Package: com.tw.common.ftp
         * @Description:上传文件
         * @param filepath
         * @param filename
         * @param inputStream
         * @return
         * @AuthorOriginally DSY
         * @date 2017年4月12日 下午3:42:26
         */
	public static Boolean uploadFile(String key,String filepath, String filename, InputStream inputStream) {
		// 初始表示上传失败
		Boolean uploadSuccess = false;
		FTPClient ftpClient = createConnection(key);
		if (ftpClient != null) {

			// 判断目录是否存在，若存在，进入该目录，若不存在，新建并进入该目录
			boolean isExist = false;
			try {
				isExist = createAndChangeDirectory(filepath);
				if (!isExist) {// 若为false，创建目录失败，关闭ftp连接并退出
					ftpClient.disconnect();
					return uploadSuccess;
				}
				// 将上传文件存储到指定目录
				uploadSuccess = ftpClient.storeFile(filename, inputStream);
				logger.debug("ftpServer upload success");
			} catch (IOException e) {
				logger.error("ftpServer upload failed");
				e.printStackTrace();
			} finally {
				try {
					// 关闭输入流
					inputStream.close();
					// 退出ftp
					ftpClient.logout();
					if (ftpClient.isConnected()) {
						ftpClient.disconnect();
					}
				} catch (IOException ioe) {
					
				}
			}
		}
		return uploadSuccess;
	}
	public static boolean createAndChangeDirectory(String filePath) throws IOException {
		return createAndChangeDirectory(defaultKey,filePath);
	}
		/**
         * @Title: createAndChangeDirectory
         * @Class: FtpUtils.java
         * @Package: com.dths.core
         * @Description:
         * @param filePath
         *            :要检查的ftp服务器
         * @param filePath
         *            ：文件路径
         * @return
         * @throws IOException
         * @AuthorOriginally LQY
         * @date 2017年4月10日 下午2:28:52
         */
	public static boolean createAndChangeDirectory(String key,String filePath) throws IOException {
		boolean existFlag = false;
		try {
			if (filePath != null && !filePath.equals("")) {
				FTPClient ftpClient = createConnection(key);
				if (ftpClient != null) {
					int index = 0;
					while ((index = filePath.indexOf("/")) != -1) {
						if (!ftpClient.changeWorkingDirectory(filePath.substring(0, index))) {
							ftpClient.makeDirectory(filePath.substring(0, index));
							ftpClient.changeWorkingDirectory(filePath.substring(0, index));
						}
						filePath = filePath.substring(index + 1, filePath.length());
					}
					if (!filePath.equals("")) {
						if (!ftpClient.changeWorkingDirectory(filePath)) {
							ftpClient.makeDirectory(filePath);
							ftpClient.changeWorkingDirectory(filePath);
						}
					}
					existFlag = true;
					logger.debug("ftpServer createAndChangeDirectory success");
				}
			}
		} catch (Exception e) {
			logger.error("ftpServer createAndChangeDirectory failed");
			e.printStackTrace();
		}
		return existFlag;
	}

	public static Boolean downFile(String fileServerPath,String ftpUrl,String localPath) {

		return downFile(defaultKey,fileServerPath,ftpUrl,localPath);
	}
		/**
         * @Title: downFile
         * @Class: FtpUtil.java
         * @Package: com.tw.common.ftp
         * @Description:下载文件
         * @param ftpUrl
         * @return
         * @AuthorOriginally DSY
         * @date 2017年4月12日 下午4:31:29
         */
	public static Boolean downFile(String key,String fileServerPath,String ftpUrl,String localPath) {
		boolean result = false;
		FTPClient ftpClient = createConnection(key);
        try {

			if (ftpClient != null) {
        		// 判断目录是否存在，若存在，进入该目录
    			boolean isExist = false;
        		String filepath = fileServerPath+ftpUrl.substring(0, ftpUrl.lastIndexOf("/"));
				String filename = ftpUrl.substring(ftpUrl.lastIndexOf("/") + 1);
				isExist = ftpClient.changeWorkingDirectory(filepath);
				if (!isExist) {// 若为false，创建目录失败，关闭ftp连接并退出
	                                                                                            				ftpClient.disconnect();
					return null;
				}
				 // 获取文件列表
	            FTPFile[] fs = ftpClient.listFiles();
	            for (FTPFile ff : fs) {
	                if (ff.getName().equals(filename)) {
	                    File localFile = new File(localPath);
	                    File dir = new File(localPath.substring(0,localPath.lastIndexOf("/")));
	                    if(!dir.exists()){
	                    	dir.mkdirs();
	                    }
	                    OutputStream is = new FileOutputStream(localFile);
	                    ftpClient.retrieveFile(ff.getName(), is);
	                    is.close();
	                    break;
	                }
	            }
	            logger.debug("ftpServer downFile success");
	            result = true;
        	}
        } catch (IOException e) {
        	logger.error("ftpServer downFile failed");
            e.printStackTrace();
        } finally {
            try {
            	ftpClient.logout();
            	if (ftpClient.isConnected()) {
                    ftpClient.disconnect();
                }
            } catch (IOException ioe) {
            }
        }
        return result;
	}

	public static Boolean downFiles(String fileServerPath,String localPath) {

		return downFiles(defaultKey,fileServerPath,localPath);
	}
	/**
	 * @Title: downFile
	 * @Class: FtpUtil.java
	 * @Package: com.tw.common.ftp
	 * @Description:下载文件
	 * @param localPath
	 * @return
	 * @AuthorOriginally DSY
	 * @date 2017年4月12日 下午4:31:29
	 */
	public static Boolean downFiles(String key,String fileServerPath,String localPath) {
		boolean result = false;
		FTPClient ftpClient = createConnection(key);
		try {

			if (ftpClient != null) {
				// 获取文件列表
				FTPFile[] fs = ftpClient.listFiles();
				for (FTPFile ff : fs) {

					downloadFile(ftpClient,ff,  localPath , fileServerPath);

				}
				logger.debug("ftpServer downFile success");
				result = true;
			}
		} catch (IOException e) {
			logger.error("ftpServer downFile failed");
			e.printStackTrace();
		} finally {
			try {
				ftpClient.logout();
				if (ftpClient.isConnected()) {
					ftpClient.disconnect();
				}
			} catch (IOException ioe) {
			}
		}
		return result;
	}


	/**
	 * 下载FTP文件
	 * 当你需要下载FTP文件的时候，调用此方法
	 * 根据<b>获取的文件名，本地地址，远程地址</b>进行下载
	 *
	 * @param ftpFile
	 * @param relativeLocalPath
	 * @param relativeRemotePath
	 */
	private static void downloadFile(FTPClient ftpClient , FTPFile ftpFile, String relativeLocalPath, String relativeRemotePath) {
		if (ftpFile.isFile()) {
			if (ftpFile.getName().indexOf("?") == -1) {
				OutputStream outputStream = null;
				try {
					File locaFile = new File(relativeLocalPath + ftpFile.getName());
//					String substring = relativeLocalPath.substring(relativeLocalPath.lastIndexOf("/",relativeLocalPath.lastIndexOf("/")-1)+1,relativeLocalPath.lastIndexOf("/"));
//					if("in".equals(substring)){//只下载in中的文件
//
//					}
					//判断文件是否存在，存在则返回
					if (locaFile.exists()) {
						return;
					} else {
						outputStream = new FileOutputStream(relativeLocalPath + ftpFile.getName());
						ftpClient.setControlEncoding("GBK");
						ftpClient.retrieveFile(ftpFile.getName(), outputStream);
						outputStream.flush();
						outputStream.close();
					}
				} catch (Exception e) {
					logger.error(e.getMessage());
				} finally {
					try {
						if (outputStream != null) {
							outputStream.close();
						}
					} catch (IOException e) {
						logger.error("输出文件流异常");
					}
				}
			}
		} else {
			String newlocalRelatePath = relativeLocalPath + ftpFile.getName();
			String newRemote = new String(relativeRemotePath + ftpFile.getName().toString());
			File fl = new File(newlocalRelatePath);
			if (!fl.exists()) {
				fl.mkdirs();
			}
			try {
				newlocalRelatePath = newlocalRelatePath + '/';
				newRemote = newRemote + "/";
				String currentWorkDir = ftpFile.getName().toString();
				boolean changedir = ftpClient.changeWorkingDirectory(currentWorkDir);
				if (changedir) {
					FTPFile[] files = null;
					files = ftpClient.listFiles();
					for (int i = 0; i < files.length; i++) {
						downloadFile(ftpClient,files[i], newlocalRelatePath, newRemote);
					}
				}
				if (changedir) {
					ftpClient.changeToParentDirectory();
				}
			} catch (Exception e) {
				logger.error(e.getMessage());
			}
		}
	}

	public static boolean deleteFile(String serverpath, String fileName) {
		return deleteFile(defaultKey,serverpath,fileName);
	}
		/**
         * @Title: deleteFile
         * @Class: FtpUtil.java
         * @Package: com.tw.common.ftp
         * @Description:删除文件
         * @param serverpath
         * @param fileName
         * @return
         * @AuthorOriginally DSY
         * @date 2017年4月19日 下午5:32:48
         */
	public static boolean deleteFile(String key,String serverpath, String fileName) {
		// 初始表示下载失败
		boolean success = false;
		FTPClient ftpClient = createConnection(key);
		if (ftpClient != null) {
			// 判断目录是否存在，若存在，进入该目录
			// 转到指定下载目录
			boolean isExist;
			try {
				isExist = ftpClient.changeWorkingDirectory(serverpath);
				if (!isExist) {
					ftpClient.disconnect();
					return success;
				}
				// 删除该目录下文件
				success = ftpClient.deleteFile(fileName);
				logger.debug("ftpServer deleteFile success");
			} catch (IOException e) {
				logger.debug("ftpServer deleteFile failed");
				e.printStackTrace();
			} finally {
				if (ftpClient.isConnected()) {
					try {
						// 退出ftp
						ftpClient.logout();
						ftpClient.disconnect();
					} catch (IOException ioe) {
					}
				}
			}
		}
		return success;
	}

	public static boolean copyFile(String from, String to,boolean isdel) {
		return copyFile(defaultKey,from,to,isdel);
	}
	/**
	 * @Title: copyFile
	 * @Class: FtpUtil.java
	 * @Package: com.tw.common.ftp
	 * @Description:复制文件
	 * @param from
	 * @param to
	 * @return
	 * @AuthorOriginally DSY
	 * @date 2017年4月19日 下午5:51:14
	 */
	public static boolean copyFile(String key,String from, String to,boolean isdel) {
        boolean copyFalg = false;
        FTPFile[] filelist;
		FTPClient ftpClient = createConnection(key);
        ByteArrayOutputStream fos=new ByteArrayOutputStream();
        ByteArrayInputStream in=null;
        try {
        	if (ftpClient != null) {
        		ftpClient.setBufferSize(1024);
        		
        		// 枚举当前from目录所有文件+子目录
                filelist = ftpClient.listFiles(from);
                int length = filelist.length;
                FTPFile ftpFile = null;
                
                for (int i = 0; i < length; i++) {
                    ftpFile = filelist[i];
                    if (ftpFile.isFile()) {
                        // 如果是文件则复制文件
                        //long l = ftpFile.getSize();
                        //ftpClient.setRestartOffset(13000);
                    	
                        ftpClient.retrieveFile(from, fos);
                        // 复制文件时掉用了retrieveFileStream方法
                        // 调用完之后必须调用completePendingCommand释放,否则FTP会断开连接
                        /*if (!ftpClient.completePendingCommand()) {
                            copyFalg = false;
                            return copyFalg;
                        }*/
                        // 如果读取的文件流不为空则复制文件
                        if (fos != null) {
                        	in=new ByteArrayInputStream(fos.toByteArray());
                            copyFalg = ftpClient.storeFile(to, in);
                            if (!copyFalg) {
                                return copyFalg;
                            }
							if(isdel){
								deleteFile(from.substring(0,from.lastIndexOf("/")),ftpFile.getName());
							}
                        }

                    } else if (ftpFile.isDirectory()) {
                        // 如果是目录则先创建该目录
                        copyFalg = ftpClient.makeDirectory(to);
                        // 再进入子目录进行递归复制
                        copyFile(key,from, to,isdel);
                    }
                }
        	}
        } catch (IOException e) {
            logger.error("FtpClientUtil.copyDirectory failed. caused by " + e.getMessage(), e);
            copyFalg = false;
        }finally {
            try {
            	// 关闭文件流
            	if(fos != null)
            		fos.close();
            	if(in != null)
            		in.close();
				if (ftpClient.isConnected()) {
					// 退出ftp
					ftpClient.logout();
					ftpClient.disconnect();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    		
		}
        return copyFalg;

    }

	/**
	 * @Description //移动本地文件
	 * @Param [srcPathStr, desPathStr]
	 * @return void
	 * @Author 田子强
	 * @Date 11:16 2022/2/25
	 **/
	public static boolean copy(String oldPath, String newPath) throws IOException {
		boolean copyFalg = false;
		File oldFile = new File(oldPath);
		File newFile = new File(newPath);
		if(oldFile.isFile()){
			copyFalg = oldFile.renameTo(newFile);
		}else if (oldFile.isDirectory()) {
			File[] files = oldFile.listFiles();
			for (File file:files) {
				// 再进入子目录进行递归复制
				copy(oldPath+file.getName() , newPath+file.getName());
			}

		}
		return copyFalg;
	}

	public static void main(String[] args) throws IOException {
//		File file = new File("C:\\Users\\tianz\\Desktop\\ediFiles\\hmg\\in\\TSG01_GO_20220223145556.txt");
//		FtpUtil.copy(file.getPath(),file.getPath().replace("\\in","\\fail"));
//		FtpUtil.copy("C:\\Users\\tianz\\Desktop\\ediFiles\\hmg\\in\\TSG01_GI_20220223145056.txt","C:\\Users\\tianz\\Desktop\\ediFiles\\hmg\\fail\\TSG01_GI_20220223145056.txt");
//		String[] splits = file.getPath().split("\\\\");
//
//		int length = splits.length-1;
//		System.out.println(splits[length-2] + "\\" + splits[length-1] + "\\" + splits[length]);
//		System.out.println(splits[length-2] + "\\fail\\" + splits[length]);
//		FtpUtil.copyFile(splits[length-2] + "\\" + splits[length-1] + "\\" + splits[length] ,splits[length-2] + "\\fail\\" + splits[length]);

//		File oldFile = new File("C:/Users/tianz/Desktop/ediFiles/hmg/in/TSG01_GO_20220223145556.txt");
//		File newFile = new File("C:/Users/tianz/Desktop/ediFiles/hmg/fail/TSG01_GO_20220223145556.txt");
//		boolean b = oldFile.renameTo(newFile);
//		System.out.println(b);
		File oldFile = new File("C:\\Users\\tianz\\Desktop\\ediFiles\\hmg\\in\\TSG01_GO_20220223145556.txt");
		File newFile = new File("C:\\Users\\tianz\\Desktop\\ediFiles\\hmg\\fail\\TSG01_GO_20220223145556.txt");
		if(oldFile.isFile()) {
			FileUtil.copyFile(oldFile, newFile);
			oldFile.delete();
		}
	}



}


